﻿//博客：http://www.cnblogs.com/munet
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Agile.DataAccess
{
    /// <summary>
    /// 数据访问上下文
    /// </summary>
    public class DataContext : IDataContext
    {
        /// <summary>
        /// 数据库连接对象
        /// </summary>
        public IDbConnection Connection
        {
            get
            {
                var connection = (IDbConnection)_Context.Data.AdoNetProvider.CreateConnection();
                connection.ConnectionString = _Context.Data.ConnectionString;
                return connection;
            }
        }

        /// <summary>
        /// 数据库上下文
        /// </summary>
        private IDbContext _Context;

        /// <summary>
        /// 输出执行Sql脚本
        /// </summary>
        /// <param name="script"></param>
        public delegate void OutputFormatScript(string script);

        /// <summary>
        /// 执行前输出执行Sql时间
        /// </summary>
        public event EventHandler OutputFormatSql;

        private object _Lock = new object();

        /// <summary>
        /// 构造函数，从指定的配置名称，创建数据库上下文，ConnectionStrings[配置名]，创建DataContext
        /// </summary>
        /// <param name="connectionName">配置名，默认"Default"</param>
        public DataContext(string connectionName = "Default")
        {
            string connectionString = "", ProviderName = "";
            try
            {
                ConnectionStringSettings connection = ConfigurationManager.ConnectionStrings[connectionName];
                connectionString = connection.ConnectionString;
                ProviderName = connection.ProviderName;
                if (string.IsNullOrWhiteSpace(connectionString))
                    throw new Exception();
                if (string.IsNullOrWhiteSpace(ProviderName))
                    throw new Exception();
            }
            catch
            {
                throw new Exception(string.Format("名称为[{0}]的配置信息不存在或者为空.", connectionName));
            }
            _Context = this.CreateIDbContext(connectionString, this.ProviderParse(ProviderName));
        }

        /// <summary>
        /// 构造函数，从数据库连接字符串和数据库类型字符串名创建DataContext
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库类型字符串</param>
        public DataContext(string connectionString, string providerName)
        {
            _Context = CreateIDbContext(connectionString, this.ProviderParse(providerName));
        }

        /// <summary>
        /// 构造函数，从数据库连接字符串和数据库类型枚举名创建DataContext
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="dataProvider">数据库类型</param>
        public DataContext(string connectionString, DataProvider dataProvider)
        {
            _Context = CreateIDbContext(connectionString, dataProvider);
        }

        private DataContext(IDbContext context)
        {
            _Context = context;
            _Context.OnError(ErrorMessage);
            _Context.OnExecuting(Executing);
        }

        private IDbContext CreateIDbContext(string connectionString, DataProvider dataProvider)//创建DataBaseContext
        {
            IDbProvider dbProvider = null;
            switch (dataProvider)
            {
                case DataProvider.Access:
                    dbProvider = new AccessProvider();
                    break;
                case DataProvider.Oracle:
                    dbProvider = new OracleProvider();
                    break;
                case DataProvider.DB2:
                    dbProvider = new DB2Provider();
                    break;
                case DataProvider.Postgre:
                    dbProvider = new PostgreSqlProvider();
                    break;
                case DataProvider.Sqlite:
                    dbProvider = new SqliteProvider();
                    break;
                case DataProvider.SqlServerCe:
                    dbProvider = new SqlServerCompactProvider();
                    break;
                case DataProvider.MySql:
                    dbProvider = new MySqlProvider();
                    break;
                case DataProvider.Sybase:
                    dbProvider = new SybaseProvider();
                    break;
                default:
                    dbProvider = new SqlServerProvider();
                    break;
            }
            if (this.IsBase64String(connectionString))
                connectionString = System.Text.Encoding.Default.GetString(Convert.FromBase64String(connectionString));
            IDbContext dbContext = new DbContext().ConnectionString(connectionString, dbProvider);
            dbContext.OnError(ErrorMessage);
            dbContext.OnExecuting(Executing);
            dbContext.IgnoreIfAutoMapFails(false);
            return dbContext;
        }

        /// <summary>
        /// 从指定的配置名称，创建数据库上下文，ConnectionStrings[配置名]，创建DataContext
        /// </summary>
        /// <param name="connectionName">配置名，默认"Default"</param>
        /// <returns></returns>
        public IDataContext CreateContext(string connectionName = "Default")
        {
            return new DataContext(connectionName);
        }

        /// <summary>
        /// 从数据库连接字符串和数据库类型字符串名创建DataContext
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="providerName">数据库类型</param>
        /// <returns></returns>
        public IDataContext CreateContext(string connectionString, string providerName)
        {
            return new DataContext(connectionString, providerName);
        }

        /// <summary>
        /// 从数据库连接字符串和数据库类型字符串名创建DataContext
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="dataProvider">数据库类型</param>
        /// <returns></returns>
        public IDataContext CreateContext(string connectionString, Agile.DataAccess.DataProvider dataProvider)
        {
            return new DataContext(connectionString, dataProvider);
        }

        private bool IsBase64String(string input)//判断是否是Base64字符串
        {
            try
            {
                Convert.FromBase64String(input);
                return true;
            }
            catch { return false; }
        }

        private DataProvider ProviderParse(string providerName)//转换DataProvider
        {
            DataProvider dataProvider;
            if (!Enum.TryParse<DataProvider>(providerName, out dataProvider))
            {
                if (providerName.ToLower().Contains("sqlite"))
                    dataProvider = DataProvider.Sqlite;
                else if (providerName.ToLower().Contains("access"))
                    dataProvider = DataProvider.Access;
                else if (providerName.ToLower().Contains("mysql"))
                    dataProvider = DataProvider.MySql;
                else if (providerName.ToLower().Contains("oracle"))
                    dataProvider = DataProvider.Oracle;
                else if (providerName.ToLower().Contains("postgre") || providerName.ToLower().Contains("pgsql"))
                    dataProvider = DataProvider.Postgre;
                else if (providerName.ToLower().Contains("sybase"))
                    dataProvider = DataProvider.Sybase;
                else if (providerName.ToLower().Contains("db2") || providerName.ToLower().Contains("ibm"))
                    dataProvider = DataProvider.DB2;
                else if (providerName.ToLower().Contains("sqlserverce") || providerName.ToLower().Contains("sqlce"))
                    dataProvider = DataProvider.SqlServerCe;
                else if (providerName.ToLower().Contains("sqlserver"))
                    dataProvider = DataProvider.SqlServer;
                else
                    throw new Exception("ProviderName 数据库类型错误.");
            }
            return dataProvider;
        }

        private void Executing(CommandEventArgs e)
        {
            this.BuildScript(e.Command, "正常");
        }

        private void BuildScript(System.Data.IDbCommand command, string type = "", string massage = "")
        {
            try
            {
                string script = command.CommandText;
                if (command.CommandType == System.Data.CommandType.Text)
                {
                    if (command.Parameters.Count > 0)
                    {
                        foreach (System.Data.IDataParameter item in command.Parameters)
                        {
                            StringBuilder temp = new StringBuilder();
                            temp.Append("'").Append(item.Value.ToString().Replace("'", "''")).Append("'");
                            if (item.Value == DBNull.Value)
                                script = ReplaceEx(script, item.ParameterName, "NULL");
                            else if (item.Value == null || item.Value is int || item.Value is decimal || item.Value is long || item.Value is double || item.Value is float)
                                script = ReplaceEx(script, item.ParameterName, item.Value.ToString());
                            else
                                script = ReplaceEx(script, item.ParameterName, temp.ToString());
                            temp.Clear();
                        }
                    }
                }
                else
                {
                    StringBuilder parameter = new StringBuilder();
                    parameter.Append(" ");
                    if (command.Parameters.Count > 0)
                    {
                        foreach (System.Data.IDataParameter item in command.Parameters)
                        {
                            if (item.Value == null || item.Value is int || item.Value is decimal || item.Value is long || item.Value is double || item.Value is float)
                                parameter.Append(item.Value.ToString()).Append(" , ");
                            else
                                parameter.Append("'").Append(item.Value.ToString().Replace("'", "''")).Append("'").Append(" , ");
                        }
                        parameter.Remove(parameter.Length - 2, 2);
                    }
                    script = "EXEC " + script;
                    script += parameter.ToString();
                    parameter.Clear();
                }

                OutputFormatScript dlgt = new OutputFormatScript(Output);
                dlgt.BeginInvoke(type + "|&|" + massage + script.ToString(), null, null);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void Output(string script)
        {
            lock (_Lock)
            {
                if (OutputFormatSql != null)
                    OutputFormatSql(script, null);
            }
        }

        private void ErrorMessage(ErrorEventArgs e)
        {
            string massage = string.Format("Error：{0}\r\n", e.Exception.Message);
            this.BuildScript(e.Command, "异常", massage);
            throw e.Exception;
        }

        private string ReplaceEx(string original, string pattern, string replacement)
        {
            int count, position0, position1;
            count = position0 = position1 = 0;
            string upperString = original.ToUpper();
            string upperPattern = pattern.ToUpper();
            int inc = (original.Length / pattern.Length) * (replacement.Length - pattern.Length);
            char[] chars = new char[original.Length + Math.Max(0, inc)];
            while ((position1 = upperString.IndexOf(upperPattern, position0)) != -1)
            {
                for (int i = position0; i < position1; ++i) chars[count++] = original[i];
                for (int i = 0; i < replacement.Length; ++i) chars[count++] = replacement[i];
                position0 = position1 + pattern.Length;
            }
            if (position0 == 0) return original;
            for (int i = position0; i < original.Length; ++i) chars[count++] = original[i];
            return new string(chars, 0, count);

        }

        /// <summary>
        /// 设置执行命令超时时间，单位(秒)
        /// </summary>
        public int CommandTimeout
        {
            get
            {
                return _Context.Data.CommandTimeout;
            }
            set
            {
                _Context.Data.CommandTimeout = value <= 0 ? 30 : value;
            }
        }

        /// <summary>
        /// 是否忽略自动映射完全匹配
        /// </summary>
        public bool IsIgnoreAutoMapFails
        {
            get
            {
                return _Context.Data.IgnoreIfAutoMapFails;
            }
            set
            {
                _Context.Data.IgnoreIfAutoMapFails = value;
            }
        }

        /// <summary>
        ///  执行T-SQL语句
        /// </summary>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IDbCommand Script(string sql, bool output = true, int commandTimeout = 30)
        {
            var builder = _Context.Script(sql);
            builder.Data.Output = output;
            builder.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout;
            return builder;
        }

        /// <summary>
        /// 生成查询语句并填充模型
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IQueryBuilder<T> Builder<T>(bool output = true, int commandTimeout = 30)
        {
            var builder = _Context.Builder<T>();
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名创建查询语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public ISelectBuilder Select(string tableName, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Select(tableName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名创建查询语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public ISelectBuilder<T> Select<T>(string tableName = "", bool output = false, int commandTimeout = 30)
        {
            string table = string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName;
            var builder = _Context.Select<T>(table);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名创建更新语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IUpdateBuilder Update(string tableName, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Update(tableName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建更新语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IUpdateBuilder<T> Update<T>(T item, string tableName, bool output = false, int commandTimeout = 30)
        {
            string table = string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName;
            var builder = _Context.Update<T>(item, table);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建更新语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IUpdateBuilder<T> Update<T>(T item, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Update<T>(item, typeof(T).Name);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名创建插入语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IInsertBuilder Insert(string tableName, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Insert(tableName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建插入语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IInsertBuilder<T> Insert<T>(T item, string tableName, bool output = false, int commandTimeout = 30)
        {
            string table = string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName;
            var builder = _Context.Insert<T>(item, table);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建插入语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IInsertBuilder<T> Insert<T>(T item, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Insert<T>(item, typeof(T).Name);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名创建删除语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IDeleteBuilder Delete(string tableName, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Delete(tableName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建删除语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IDeleteBuilder<T> Delete<T>(T item, string tableName, bool output = false, int commandTimeout = 30)
        {
            string table = string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName;
            var builder = _Context.Delete<T>(item, table);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体创建删除语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IDeleteBuilder<T> Delete<T>(T item, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Delete<T>(item, typeof(T).Name);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据表名及字段判断数据库记录是否存在
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IExistsBuilder Exists(string tableName, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Exists(tableName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体判断数据库记录是否存在
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IExistsBuilder<T> Exists<T>(T item, string tableName, bool output = false, int commandTimeout = 30)
        {
            string table = string.IsNullOrWhiteSpace(tableName) ? typeof(T).Name : tableName;
            var builder = _Context.Exists<T>(item, table);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 根据实体判断数据库记录是否存在
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IExistsBuilder<T> Exists<T>(T item, bool output = false, int commandTimeout = 30)
        {
            var builder = _Context.Exists<T>(item, typeof(T).Name);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="procedureName">存储过程名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IStoredProcedureBuilder Procedure(string procedureName, bool output = true, int commandTimeout = 30)
        {
            var builder = _Context.Procedure(procedureName);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="procedureName">存储过程名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IStoredProcedureBuilder<T> Procedure<T>(T item, string procedureName, bool output = true, int commandTimeout = 30)
        {
            string procedure = string.IsNullOrWhiteSpace(procedureName) ? typeof(T).Name : procedureName;
            var builder = _Context.Procedure<T>(item, procedure);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        public IStoredProcedureBuilder<T> Procedure<T>(T item, bool output = true, int commandTimeout = 30)
        {
            var builder = _Context.Procedure<T>(item, typeof(T).Name);
            builder.Data.Command.Data.Output = output;
            builder.Data.Command.Data.InnerCommand.CommandTimeout = commandTimeout <= 0 ? 30 : commandTimeout; ;
            return builder;
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        public IDbContext Commit()
        {
            return _Context.Commit();
        }

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <returns></returns>
        public IDbContext Rollback()
        {
            return _Context.Rollback();
        }

        /// <summary>
        /// 开始事务，此方法执行后必须调用Dispose.
        /// </summary>
        /// <param name="userTransaction"></param>
        /// <returns></returns>
        public IDataContext UseTransaction(bool userTransaction = true)
        {
            IDbContext context = _Context.UseTransaction(userTransaction);
            return new DataContext(context);
        }

        /// <summary>
        /// 共享数据库连接，此方法执行后必须调用Dispose.
        /// </summary>
        /// <param name="useSharedConnection"></param>
        /// <returns></returns>
        public IDataContext UseSharedConnection(bool useSharedConnection = true)
        {
            IDbContext context = _Context.UseSharedConnection(useSharedConnection);
            return new DataContext(context);
        }

        /// <summary>
        /// 支持返回多个数据集的Command，此方法执行后必须调用Dispose.
        /// </summary>
        /// <returns></returns>
        public IDbCommand MultiResultCommand()
        {
            return _Context.MultiResultSql;
        }

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        public void Dispose()
        {
            _Context.Dispose();
        }
    }
}

